/**
 * Copyright 2024 The Vitess Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { useEffect, useState } from 'react';
import { Link, useHistory } from 'react-router-dom';

import style from './CreateSchemaMigration.module.scss';
import { useApplySchema, useClusters, useKeyspaces } from '../../../hooks/api';
import { useDocumentTitle } from '../../../hooks/useDocumentTitle';
import { Label } from '../../inputs/Label';
import { Select } from '../../inputs/Select';
import { ContentContainer } from '../../layout/ContentContainer';
import { NavCrumbs } from '../../layout/NavCrumbs';
import { WorkspaceHeader } from '../../layout/WorkspaceHeader';
import { WorkspaceTitle } from '../../layout/WorkspaceTitle';
import { TextInput } from '../../TextInput';
import { success } from '../../Snackbar';
import { FormError } from '../../forms/FormError';
import { vtadmin } from '../../../proto/vtadmin';
import ErrorDialog from '../../dialog/ErrorDialog';

interface FormData {
    clusterID: string;
    keyspace: string;
    ddlStrategy: string;
    sql: string;
    batchSize: number;
    callerID: string;
    migrationContext: string;
    uuidList: string;
}

const DEFAULT_FORM_DATA: FormData = {
    clusterID: '',
    keyspace: '',
    // Default DDL Strategy set to "vitess".
    ddlStrategy: 'vitess',
    sql: '',
    batchSize: 0,
    callerID: '',
    migrationContext: '',
    uuidList: '',
};

const DDL_STRATEGY_HELP_TEXT = `Online DDL strategy, compatible with @@ddl_strategy session variable (default "vitess")`;

const MIGRATION_CONTEXT_HELP_TEXT =
    'For Online DDL, optionally supply a custom unique string used as context for the migration(s) in this command. By default a unique context is auto-generated by Vitess.';

const CALLER_ID_HELP_TEXT =
    'Effective caller ID used for the operation and should map to an ACL name which grants this identity the necessary permissions to perform the operation (this is only necessary when strict table ACLs are used)';

export const CreateSchemaMigration = () => {
    useDocumentTitle('Create Schema Migration Request');

    const history = useHistory();

    const [formData, setFormData] = useState<FormData>(DEFAULT_FORM_DATA);

    const [clusterKeyspaces, setClusterKeyspaces] = useState<vtadmin.Keyspace[]>([]);

    const [errorDialogOpen, setErrorDialogOpen] = useState<boolean>(false);

    const { data: clusters = [], ...clustersQuery } = useClusters();

    const { data: keyspaces = [], ...keyspacesQuery } = useKeyspaces();

    const mutation = useApplySchema(
        {
            clusterID: formData.clusterID,
            keyspace: formData.keyspace,
            callerID: formData.callerID,
            sql: formData.sql,
            request: {
                ddl_strategy: formData.ddlStrategy,
                batch_size: formData.batchSize,
                migration_context: formData.migrationContext,
                uuid_list: (formData.uuidList && formData.uuidList.split(',').map((uuid) => uuid.trim())) || undefined,
            },
        },
        {
            onSuccess: () => {
                success(`Successfully created schema migration request.`, { autoClose: 1600 });

                history.push({
                    pathname: `/migrations`,
                    search: `?keyspace=${formData.keyspace}&cluster=${formData.clusterID}`,
                });
            },
            onError: () => {
                setErrorDialogOpen(true);
            },
        }
    );

    let selectedCluster = null;
    if (!!formData.clusterID) {
        selectedCluster = clusters.find((c) => c.id === formData.clusterID);
    }

    let selectedKeyspace = null;
    if (!!formData.keyspace) {
        selectedKeyspace = keyspaces.find((ks) => ks.keyspace?.name === formData.keyspace);
    }

    const isValid = !!selectedCluster && !!formData.keyspace && !!formData.sql && !!formData.ddlStrategy;

    const isDisabled = !isValid || mutation.isLoading;

    const onSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
        e.preventDefault();
        mutation.mutate();
    };

    useEffect(() => {
        // Clear out the selected keyspaces if selected cluster is changed.
        setFormData((prevFormData) => ({ ...prevFormData, keyspace: '' }));
        setClusterKeyspaces(keyspaces.filter((ks) => ks.cluster?.id === formData.clusterID));
    }, [formData.clusterID, keyspaces]);

    useEffect(() => {
        if (clusters.length === 1) {
            setFormData((prevFormData) => ({ ...prevFormData, clusterID: clusters[0].id }));
        }
    }, [clusters]);

    return (
        <div>
            <WorkspaceHeader>
                <NavCrumbs>
                    <Link to="/migrations">Schema Migrations</Link>
                </NavCrumbs>

                <WorkspaceTitle>Create Schema Migration Request</WorkspaceTitle>
            </WorkspaceHeader>

            <ContentContainer>
                <form onSubmit={onSubmit}>
                    <div className="flex flex-row gap-4 flex-wrap mb-2">
                        <Select
                            className="block min-w-[300px]"
                            disabled={keyspacesQuery.isLoading || !selectedCluster}
                            inputClassName="block w-full"
                            itemToString={(ks) => ks?.keyspace?.name || ''}
                            items={clusterKeyspaces}
                            label="Keyspace"
                            onChange={(ks) => setFormData({ ...formData, keyspace: ks?.keyspace?.name || '' })}
                            placeholder={keyspacesQuery.isLoading ? 'Loading keyspaces...' : 'Select a keyspace'}
                            renderItem={(ks) => `${ks?.keyspace?.name}`}
                            selectedItem={selectedKeyspace}
                        />
                        <Label
                            className="block grow min-w-[300px]"
                            label="DDL Strategy"
                            helpText={DDL_STRATEGY_HELP_TEXT}
                        >
                            <TextInput
                                onChange={(e) => setFormData({ ...formData, ddlStrategy: e.target.value })}
                                value={formData.ddlStrategy}
                            />
                        </Label>
                    </div>

                    <Label label="SQL" helpText={'Semicolon-delimited, repeatable SQL commands to apply.'}>
                        <textarea
                            className={style.sqlInput}
                            onChange={(e) => setFormData({ ...formData, sql: e.target.value })}
                            rows={10}
                            value={formData.sql}
                        />
                    </Label>

                    <h3 className="mt-8 mb-2">Advanced</h3>

                    <div className="flex flex-row gap-4 flex-wrap">
                        <Label
                            className="block grow min-w-[300px]"
                            label="Batch Size"
                            helpText={
                                'How many queries to batch together. Only applicable when all queries are CREATE TABLE|VIEW'
                            }
                        >
                            <TextInput
                                onChange={(e) => setFormData({ ...formData, batchSize: Number(e.target.value) })}
                                type="number"
                                value={formData.batchSize}
                            />
                        </Label>
                        <Label className="block grow min-w-[300px]" label="Caller ID" helpText={CALLER_ID_HELP_TEXT}>
                            <TextInput
                                onChange={(e) => setFormData({ ...formData, callerID: e.target.value })}
                                value={formData.callerID}
                            />
                        </Label>
                        <Select
                            className="block grow min-w-[300px]"
                            disabled={clustersQuery.isLoading}
                            inputClassName="block w-full"
                            itemToString={(cluster) => cluster?.name || ''}
                            items={clusters}
                            label="Cluster"
                            onChange={(c) => setFormData({ ...formData, clusterID: c?.id || '' })}
                            placeholder={clustersQuery.isLoading ? 'Loading clusters...' : 'Select a cluster'}
                            renderItem={(c) => `${c?.name} (${c?.id})`}
                            selectedItem={selectedCluster}
                        />
                        <Label
                            className="block grow min-w-[300px]"
                            label="UUIDs"
                            helpText={
                                'Optional, comma-delimited, repeatable, explicit UUIDs for migration. If given, must match number of DDL changes.'
                            }
                        >
                            <TextInput
                                onChange={(e) => setFormData({ ...formData, uuidList: e.target.value })}
                                value={formData.uuidList || ''}
                            />
                        </Label>
                        <Label
                            className="block grow min-w-[300px]"
                            label="Migration Context"
                            helpText={MIGRATION_CONTEXT_HELP_TEXT}
                        >
                            <TextInput
                                onChange={(e) => setFormData({ ...formData, migrationContext: e.target.value })}
                                value={formData.migrationContext || ''}
                            />
                        </Label>
                    </div>

                    {clustersQuery.isError && (
                        <FormError
                            error={clustersQuery.error}
                            title="Couldn't load clusters. Please reload the page to try again."
                        />
                    )}

                    <div className="my-8">
                        <button className="btn" disabled={isDisabled} type="submit">
                            {mutation.isLoading ? 'Creating...' : 'Create Schema Migration Request'}
                        </button>
                    </div>
                </form>

                {mutation.isError && !mutation.isLoading && (
                    <ErrorDialog
                        errorDescription={mutation.error.message}
                        errorTitle="Error Creating Schema Migration Request"
                        isOpen={errorDialogOpen}
                        onClose={() => {
                            setErrorDialogOpen(false);
                        }}
                    />
                )}
            </ContentContainer>
        </div>
    );
};
